import { deleteJSON, getJSON, postJSON, putJSON, upload, type WebResult } from "./request";

export type ResourceType =
  | "text"
  | "audio"
  | "image"
  | "video"
  | "font"
  | "model"
  | "document"
  | "compressed"
  | "other";
export const RESOURCE_TYPE_VALUES = [
  "text",
  "audio",
  "image",
  "video",
  "font",
  "model",
  "document",
  "compressed",
  "other",
];

export function getResourceTypeByMIMEType(type: string): ResourceType {
  const [mainType, subType] = type.split("/");
  const mimeType = {
    type: mainType,
    subtype: subType,
  };
  if (
    ["text", "audio", "image", "video", "font", "model"].includes(
      mimeType.type,
    )
  ) {
    return mimeType.type as ResourceType;
  }
  if (
    [
      // doc(x)
      "x-abiword",
      "msword",
      "vnd.msword",
      "x-msword",
      "vnd.openxmlformats-officedocument.wordprocessingml.document",
      // xls(x)
      "msexcel",
      "x-msexcel",
      "vnd.msexcel",
      "vnd.openxmlformats-officedocument.spreadsheetml.sheet",
      // ppt(x)
      "vnd.ms-powerpoint",
      "vnd.openxmlformats-officedocument.presentationml.presentation",
      // pdf
      "pdf",
      "x-pdf",
      "acrobat",
      "nappdf",
      // other
      "vnd.oasis.opendocument.presentation",
      "vnd.oasis.opendocument.spreadsheet",
      "vnd.oasis.opendocument.text",
    ].includes(mimeType.subtype)
  ) {
    return mimeType.subtype as ResourceType;
  }
  if (
    [
      "x-compressed",
      "zip",
      "x-zip",
      "x-tar",
      "x-rar",
      "vnd.rar",
      "x-rar-compressed",
      "gzip",
      "x-gzip",
      "x-bzip",
      "x-bzip2",
      "x-7z-compressed",
      "java-archive",
    ].includes(mimeType.subtype)
  ) {
    return "compressed";
  }
  return "other";
}

export interface ResourceDTO {
  name?: string;
  description?: string;
  public?: boolean;
  file: File;
}

export interface ResourceChunkCodeDTO {
  name: string;
  description?: string;
  public?: boolean;
}

// 分片上传
export interface ResourceChunkDTO {
  code: string;
  index?: number;
  chunk: Blob;
}

export interface Resource {
  user: { nickname: string };
  id: number;
  uploader_id: number;
  uploader: string;
  name: string;
  description: string;
  size: number;
  type: string;
  public: boolean;
  upload_time: string;
}

export default {

  getDiskInformation() {
    return getJSON("/api/admin/resource/disk");
  },

  refresh() {
    return putJSON("/api/admin/resource/refresh");
  },

  async list(): Promise<WebResult<Resource[]>> {
    const result = await getJSON("/api/admin/resource/list");
    result.data.forEach((item: Resource) => {
      item.uploader = item.user.nickname;
    });
    return result;
  },

  getMaxFileSize() {
    return getJSON("/api/resource/max-size/file");
  },

  getMaxChunkSize() {
    return getJSON("/api/resource/max-size/chunk");
  },

  hasResource(type: ResourceType, name: string, uid?: number | string) {
    if (uid) {
      return getJSON(`/api/admin/resource/has/${type}/${uid}/${name}`);
    }
    return getJSON(`/api/admin/resource/has/${type}/${name}`);
  },
  hasSelfResource(type: ResourceType, name: string) {
    return this.hasResource(type, name, "self");
  },

  getResourceCount() {
    return getJSON("/api/admin/resource/count");
  },

  async getResourceByPage(page: number, pageSize?: number): Promise<WebResult<Resource[]>> {
    const result = await getJSON(`/api/admin/resource/page/${page}${ pageSize ? ("?pageSize=" + pageSize) : "" }`);
    if (result && result.data) {
      result.data.forEach((item: Resource) => {
        item.uploader = item.user.nickname;
      });
    }
    return result;
  },

  deleteResourceByID(id: number) {
    return deleteJSON(`/api/admin/resource/${id}`);
  },

  uploadResource(dto: ResourceDTO, onProgress?: (progress: number) => void) {
    const formData = new FormData();
    formData.append("name", dto.name || dto.file.name);
    formData.append("description", dto.description || "");
    formData.append("public", dto.public ? "true" : "false");
    formData.append("file", dto.file);
    return upload("/api/resource/upload", formData, onProgress);
  },

  startUploadChunk(dto: ResourceChunkCodeDTO) {
    return postJSON("/api/resource/chunk/start", {
      body: JSON.stringify(dto),
    });
  },
  endUploadChunk(code: string) {
    return postJSON("/api/resource/chunk/end", {
      body: JSON.stringify({ code }),
    });
  },
  uploadChunk(dto: ResourceChunkDTO, onProgress?: (progress: number) => void) {
    const formData = new FormData();
    formData.append("code", dto.code);
    formData.append("chunk", dto.chunk);
    if (dto.index) {
      formData.append("index", dto.index.toString());
    }
    return upload("/api/resource/chunk/upload", formData, onProgress);
  }
};
